package org.jeecg.modules.wx.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysTenant;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysDictService;
import org.jeecg.modules.system.service.ISysLogService;
import org.jeecg.modules.system.service.ISysTenantService;
import org.jeecg.modules.wx.common.Constant;
import org.jeecg.modules.wx.config.WxConfig;
import org.jeecg.modules.wx.service.WxTokenService;
import org.jeecg.modules.wx.utils.HttpUtil;
import org.jeecg.modules.wx.utils.RedisCacheUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author
 * @ClassName WxTokenServiceImpl
 * @Description
 * @date 2024/4/2 15:06
 * @Version 1.0
 */
@Service
@Slf4j
public class WxTokenServiceImpl implements WxTokenService {

    @Autowired
    private RedisCacheUtil redisCache;

    @Autowired
    private WxConfig config;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private ISysLogService logService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    public RedisTemplate redisTemplate; //add by nbacheng
    @Autowired
    private ISysDepartService sysDepartService;
    @Autowired
    private ISysTenantService sysTenantService;
    @Autowired
    private ISysDictService sysDictService;
    @Resource
    private BaseCommonService baseCommonService;


    /**
     * 获取微信小程序token
     * @return
     */
    @Override
    public String getToken() {
        //缓存中有从缓存中拿
        if (redisCache.getCacheObject("WxXcxToken") != null && !"".equals(redisCache.getCacheObject("WxXcxToken"))){
            return redisCache.getCacheObject("WxXcxToken");
        }

        HashMap<String, Object> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");

        HashMap<String, Object> body = new HashMap<>();
        body.put("grant_type", config.getToken_grant_type());
        body.put("appid", config.getAppid());
        body.put("secret", config.getSecret());
        body.put("force_refresh", config.isForce_refresh());

        try{
            String post = HttpUtil.post(Constant.WX_TOKEN_URL, headers, body);
            JSONObject json = JSON.parseObject(post);

            //失败
            if (json.containsKey("errcode")){
                throw new RuntimeException("获取微信小程序token失败，失败原因是："+json.get("errmsg"));
            }

            //缓存token
            redisCache.setCacheObject("WxXcxToken", json.getString("access_token"),Integer.valueOf(json.getString("expires_in")),TimeUnit.SECONDS);

            return json.get("access_token").toString();
        }catch (Exception e){
            log.error("获取微信小程序token失败，失败原因是：{}", e.getMessage());
            throw new RuntimeException("获取微信小程序token失败，失败原因是：" + e.getMessage());
        }
    }

    /**
     * 小程序登录获取用户信息
     *
     * @param code
     * @return
     */
    public JSONObject getUserInfo(String code){

        JSONObject object = new JSONObject();

        String token = getToken();

        HashMap<String, Object> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");

        HashMap<String, Object> body = new HashMap<>();
        body.put("code", code);

        try{
            String url = Constant.WX_GETPHONENUMBER_URL+"?access_token="+token+"";
            String post = HttpUtil.post(url, headers, body);

            JSONObject json = JSON.parseObject(post);

            if (json.getInteger("errcode")==0){
                //成功获取系统用户信息
                JSONObject phoneInfo = json.getJSONObject("phone_info");
                String phoneNumber = phoneInfo.getString("phoneNumber");
                SysUser sysUser = sysUserService.getUserByPhone(phoneNumber);

                if(sysUser!=null) {
                    // 生成token
                    String zf_token = JwtUtil.sign(sysUser.getUsername(), sysUser.getPassword());
                    // 设置token缓存有效时间
                    redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + zf_token, zf_token);
                    redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + zf_token, JwtUtil.EXPIRE_TIME * 2 / 6000); //过期10分钟

                    Map<String, Object> userInfo = new HashMap<>();
                    userInfo.put("username", sysUser.getUsername());
                    userInfo.put("phone", sysUser.getPhone());
                    userInfo.put("realname", sysUser.getRealname());
                    userInfo.put("number", sysUser.getWorkNo());

                    object.put("code", "200");
                    object.put("message", "登录成功");
                    object.put("token", zf_token);
                    object.put("user", userInfo);

                }else {
                    throw new RuntimeException("该员工在系统不存在，请联系管理员注册后再登录");
                }
                return object;
            }else {
                throw new RuntimeException(json.getString("errmsg"));
            }
        }catch (Exception e){
            log.error("手机快速登录获取用户信息失败，失败原因是：{}", e.getMessage());
            throw new RuntimeException("手机快速登录获取用户信息失败，失败原因是：" + e.getMessage());
        }

    }


    /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
        String syspassword = sysUser.getPassword();
        String username = sysUser.getUsername();
        // 获取用户部门信息
        JSONObject obj = new JSONObject();
        List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
        obj.put("departs", departs);
        if (departs == null || departs.size() == 0) {
            obj.put("multi_depart", 0);
        } else if (departs.size() == 1) {
            sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            obj.put("multi_depart", 1);
        } else {
            //查询当前是否有登录部门
            // update-begin--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
            SysUser sysUserById = sysUserService.getById(sysUser.getId());
            if(oConvertUtils.isEmpty(sysUserById.getOrgCode())){
                sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            }
            // update-end--Author:wangshuai Date:20200805 for：如果用戶为选择部门，数据库为存在上一次登录部门，则取一条存进去
            obj.put("multi_depart", 2);
        }
        // update-begin--Author:sunjianlei Date:20210802 for：获取用户租户信息
        String tenantIds = sysUser.getRelTenantIds();
        if (oConvertUtils.isNotEmpty(tenantIds)) {
            List<String> tenantIdList = Arrays.asList(tenantIds.split(","));
            // 该方法仅查询有效的租户，如果返回0个就说明所有的租户均无效。
            List<SysTenant> tenantList = sysTenantService.queryEffectiveTenant(tenantIdList);
            if (tenantList.size() == 0) {
                result.error500("与该用户关联的租户均已被冻结，无法登录！");
                return result;
            } else {
                obj.put("tenantList", tenantList);
            }
        }
        // update-end--Author:sunjianlei Date:20210802 for：获取用户租户信息
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
        obj.put("token", token);
        obj.put("userInfo", sysUser);
        obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }
}
